﻿using System;
using System.Security.Cryptography;

namespace org.se.fs.presenter.Library
{
    public class Cryptography
    {
        public static string Encrypt(string plainText, string passPhrase, string saltValue, string hashAlgorithm, int passwordIterations, string initVector, int keySize)
        {
            var initVectorBytes = System.Text.Encoding.ASCII.GetBytes(initVector);
            var saltValueBytes = System.Text.Encoding.ASCII.GetBytes(saltValue);
            var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
            var password = new PasswordDeriveBytes(passPhrase, saltValueBytes, hashAlgorithm, passwordIterations);
            #pragma warning disable 612,618
            var keyBytes = password.GetBytes(keySize / 8);
            #pragma warning restore 612,618
            byte[] cipherTextBytes;
            CryptoStream cryptoStream;
            
            ICryptoTransform encryptor;
            using (var symmetricKey = new RijndaelManaged { Mode = CipherMode.CBC })
            {
                encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
            }
            using (var memoryStream = new System.IO.MemoryStream())
            {
                cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
                cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
                cryptoStream.FlushFinalBlock();
                cipherTextBytes = memoryStream.ToArray();
                memoryStream.Close();
            }
            cryptoStream.Close();
            var cipherText = Convert.ToBase64String(cipherTextBytes);
            return cipherText;
        }

        public static string Decrypt(string cipherText, string passPhrase, string saltValue, string hashAlgorithm, int passwordIterations, string initVector, int keySize)
        {
            var initVectorBytes = System.Text.Encoding.ASCII.GetBytes(initVector);
            var saltValueBytes = System.Text.Encoding.ASCII.GetBytes(saltValue);
            var cipherTextBytes = Convert.FromBase64String(cipherText);
            var password = new PasswordDeriveBytes(passPhrase, saltValueBytes, hashAlgorithm, passwordIterations);
            #pragma warning disable 612,618
            var keyBytes = password.GetBytes(keySize / 8);
            #pragma warning restore 612,618
            CryptoStream cryptoStream;
            byte[] plainTextBytes;
            int decryptedByteCount;
            
            ICryptoTransform decryptor;
            using (var symmetricKey = new RijndaelManaged {Mode = CipherMode.CBC})
            {
                decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes);
            }
            using (var memoryStream = new System.IO.MemoryStream(cipherTextBytes))
            {
                cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
                plainTextBytes = new byte[cipherTextBytes.Length];
                decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
                memoryStream.Close();
            }
            cryptoStream.Close();
            var plainText = System.Text.Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
            return plainText;
        }
    }
}
